package graph_viewer.structure;

import graph_viewer.util.*;

public class Edge implements Visual_Component{
	final	public	 String DEFAULT_TYPE	= "";

	private	Node 
				start_node,
				end_node;
	private	String	 type;

	private boolean is_important;
	
	
	//============================================================================
	// constructor
	//============================================================================
	public Edge(){
		set_type( DEFAULT_TYPE );
		set_is_important( true );
	}
	
	public Edge( Node start_node, Node end_node ){
		this();

		set_start_node( start_node );
		set_end_node( end_node );
	}

	public Edge( Node start_node, Node end_node, String a_type ){
		this( start_node, end_node );
		set_type( a_type );
	}

	public Edge( Edge an_edge ){
		this( new Node( an_edge.get_start_node() ), new Node ( an_edge.get_end_node() ), an_edge.get_type() );
	}
	
	//============================================================================
	// setter & getter
	//============================================================================
	public void set_start_node( Node a_start_node){
		this.start_node	= a_start_node;
	}

	public void set_end_node( Node a_end_node ){
		this.end_node	= a_end_node;
	}

	public Node get_start_node(){
		return this.start_node;
	}

	public Node get_end_node(){
		return this.end_node;
	}

	public String get_type(){
		return this.type;
	}

	public void set_type( String a_type ){
		this.type	 = a_type;
	}
	
	public void set_is_important( boolean a_status ){
		this.is_important	= a_status;
	}

	public boolean get_is_important(){
		return this.is_important;
	}
	//============================================================================
	// public methods
	//============================================================================
	/*public void replace_node( Node end, Node new_end){
		if ( is_start_node( end ) ){
			set_start_node( new_end );
		}else if ( is_end_node( end ) ){
			set_end_node( new_end );
		}
	}
	*/
	/**
	// technically, there are three situation: 
	// 1. start node bottom point(sb) higher than end node top point(et), 
	// 2. start node top point (st)lower than end node bottom point(eb),
	// 3. st > et > sb, or et > st > eb
	//	3.1 start node right to end node
	//	3.2 start node left to end node
	// @return 1 sb-et
	//		 2 st-eb
	//		 3.1 slm-erm(start node left middle, end node right middle)
	//		 3.2 srm-elm(start node right middle, end node left middle)
	// NB: the two nodes are not override each other.
	// in implementaion:
	// if sb > et return sb-et;
	// else slm-erm, or srm-elm
	 * get the start point and end point of the edge
	 * @return int[]	int[0] start_x, 
	 * 			int[1] start_y,
	 * 			int[2] end_x,
	 * 			int[3] end_y.
	 */
	public int[] find_start_end_location(){
		int[] connect_points	= new int[ 4 ];
		Node_Position
			start	= get_start_node().get_position(),
			end		= get_end_node().get_position();
		//start is above the end	
		if ( start.is_above( end )){
			connect_points[0]	= start.get_bottom_point()[0];
			connect_points[1]	= start.get_bottom_point()[1];
			connect_points[2]	= end.get_top_point()[0];
			connect_points[3]	= end.get_top_point()[1];
		}else{//start is under end
			// if start is left to end
			if ( start.is_left(end) ){
				connect_points[0]	= start.get_right_point()[0];
				connect_points[1]	= start.get_right_point()[1];
				connect_points[2]	= end.get_left_point()[0];
				connect_points[3]	= end.get_left_point()[1];
			}else{ //start is right to end
				connect_points[0]	= start.get_left_point()[0];
				connect_points[1]	= start.get_left_point()[1];
				connect_points[2]	= end.get_right_point()[0];
				connect_points[3]	= end.get_right_point()[1];
			}		
		}
		
		return connect_points;
	}
	
	public double find_length(){
		return Layout_Util.find_nodes_distance( start_node, end_node );
	}

	public boolean is_default_type(){
		return get_type().equals( DEFAULT_TYPE );
	}
	
	public boolean is_node_of_the_edge( Node n ){
		return is_start_node( n ) || is_end_node( n );
	}

	public boolean is_start_node( Node n ){
		return n.get_label().equals( start_node.get_label() );
	}

	public boolean is_end_node( Node n ){
		return n.get_label().equals( end_node.get_label() );
	} 
		
	public String toString(){
		StringBuffer edge = new StringBuffer();

		edge.append( "Edge from node " + start_node /* + " at " + start_node.get_position() */ );
		edge.append( "\n\t to node " + end_node  /* + " at " + end_node.get_position() */  );

		return edge.toString();
	}
}
